
#include <string.h>
#include "WCI.h"
#include "ISO14443Command.h"
#include "ISO14443p4a.h"

/************************************
// 说明: 检查ATS是否有效
// 参数 ats: ATS数据
// 参数 alen: ATS长度
// 返回值:  0 - ATS无效
1 - ATS有效
************************************/
static int TypeA_VerifyATS(unsigned char ats[], unsigned int alen) {

	unsigned char T0, TA, TB, TC;
	unsigned char TL = ats[0];
	unsigned char len = 1;

	if (alen < 2 || TL != alen) {
		return 0;
	}

	T0 = ats[len++];
	if (T0 & 0x10) {
		TA = ats[len++];
	}
	if (T0 & 0x20) {
		TB = ats[len++];
	}
	if (T0 & 0x40) {
		TC = ats[len++];
	}
	(void)TA;(void)TB;(void)TC;
	if (len > alen) {
		return 0;
	}

	return 1;
}
/************************************
// 说明: 向卡片发送RATS请求
// 参数 unused_wci: 无线通信接口的指针
// 参数 cid: 分配给卡片的CID
// 参数 fsdi: 设备的FSDI
// 参数 ats: 存放ATS的存储空间的指针
// 参数 alen: 存放ATS长度的指针
// 返回值: 0 - 成功
非0 - 失败
************************************/
static int TypeA_RATS(WCI* wci, unsigned char cid, unsigned char fsdi, unsigned char *ats, unsigned int *alen) {
	int result;
	unsigned char tx[8];
	unsigned int tlen = 0;
	unsigned int rmax = 24;

	tx[tlen++] = 0xE0;
	tx[tlen++] = (fsdi << 4) | (cid & 0x0F);

	WCI_Config(wci, WCI_Cfg_RATS);
	result = WCI_Exchange(wci, tx, tlen, ats, alen, rmax, WaitTime_Ms(5, 0), FGT_A);
	if (result) {
		return result;
	}
	if (!TypeA_VerifyATS(ats, *alen)) {
		result = CmdS_Invalid;
	}
	return result;
}

int ISO14443p4a_RATS(WCI * wci, unsigned char cid, unsigned char fsdi, unsigned char * ats)
{
	unsigned int alen;
	int i;
	int ret;

	for (i = 0; i < 2; i++) {
		ret = TypeA_RATS(wci, cid, fsdi, ats, &alen);
		if (ret == WCI_S_OK) {
			break;
		}
	}
	return ret;
}


#define FWT_Diff	384
#define FWT_Calc(fwi) ((256 * 16 + FWT_Diff) << (fwi))

#define FGT_A	(1172 + 384)

enum {
	INT_TA,
	INT_TB,
	INT_TC,
};

static unsigned int parseFSC(unsigned char fsci) {
	static const unsigned short fs[] = {
		16, 24, 32, 40, 48, 64, 96, 128, 256,
		256, 256, 256, 256, 256, 256, 256
	};
	return fs[fsci & 0x0F];
}

static unsigned int parseFWT(unsigned char fwi) {
	if (fwi > 14) {
		fwi = 4;
	}
	return FWT_Calc(fwi);
}

static unsigned int parseSFGT(unsigned char fgi) {
	if (fgi > 14) {
		fgi = 0;
	}
	return 256 * 16 * (1 << fgi) + 384;
}

static unsigned char atsGet(const unsigned char ats[], unsigned char intfaceByte, unsigned char defaultValue) {
	unsigned int maps = ats[1] >> 4;
	const unsigned char* pats = &ats[2];
	unsigned int i;

	//skip front interface byte
	for (i = 0; i < intfaceByte; i++) {
		if (maps & (1 << i)) {
			pats++;
		}
	}
	//check byte present
	if (maps & (1 << i)) {
		return *pats;
	}

	return defaultValue;
}

static unsigned int Param_A_GetFGT(const unsigned char param[]) {
	// at least 1172 / fc
	(void)param;
	return FGT_A;
}
static unsigned int Param_A_GetSFGT(const unsigned char ats[]) {
	unsigned char TB = atsGet(ats, INT_TB, 0x40);
	unsigned char sfgi = TB & 0x0F;

	return parseSFGT(sfgi);
}
static unsigned int Param_A_GetFWT(const unsigned char ats[]) {
	unsigned char TB = atsGet(ats, INT_TB, 0x40);
	unsigned char fwi = TB >> 4;
	return parseFWT(fwi);
}

static unsigned int Param_A_GetFSC(const unsigned char ats[]) {
	unsigned char T0 = ats[1];
	unsigned char fsci = T0 & 0x0F;
	return parseFSC(fsci);
}

static unsigned char Param_A_GetFormat(const unsigned char ats[]) {
	unsigned char tc = atsGet(ats, INT_TC, 0);

	if (tc & 0x01) {
		tc &= ~0x01; //We not support NAD
	}
	return tc;
}


 int ISO14443p4a_GetParams(unsigned char* ats, ISO14443p4Param_T* params) {
	params->FGT = Param_A_GetFGT(ats);
	params->FWT = Param_A_GetFWT(ats);
	params->FSC = Param_A_GetFSC(ats);
	params->SFGT = Param_A_GetSFGT(ats);
	params->blockFormat = Param_A_GetFormat(ats);
	params->NAD = 0;
	params->sn = 0;
	return 0;
}